package com.coinworld.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.exceptions.JedisException;

import java.util.*;


@Component
public class RedisPool {

    @Autowired
    JedisPool jedisPool;

    @Value("${redis.pwd}")
    private String password;



    /**
     * 加锁
     * @param lockName       锁的key
     * @param acquireTimeout 获取超时时间
     * @param timeout        锁的超时时间
     * @return 锁标识
     */
    public String lockWithTimeout(String lockName, long acquireTimeout, long timeout, int index) {
        Jedis conn = null;
        String retIdentifier = null;
        try {
            // 获取连接
            conn = jedisPool.getResource();
            conn.auth(password);
            conn.select(index);
            // 随机生成一个value
            String identifier = UUID.randomUUID().toString();
            // 锁名，即key值
            String lockKey = "lock:" + lockName;
            // 超时时间，上锁后超过此时间则自动释放锁
            int lockExpire = (int) (timeout / 1000);

            // 获取锁的超时时间，超过这个时间则放弃获取锁
            long end = System.currentTimeMillis() + acquireTimeout;
            while (System.currentTimeMillis() < end) {
                if (conn.setnx(lockKey, identifier) == 1) {
                    conn.expire(lockKey, lockExpire);
                    // 返回value值，用于释放锁时间确认
                    retIdentifier = identifier;
                    return retIdentifier;
                }
                // 返回-1代表key没有设置超时时间，为key设置一个超时时间
                if (conn.ttl(lockKey) == -1) {
                    conn.expire(lockKey, lockExpire);
                }

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        } catch (JedisException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return retIdentifier;
    }

    /**
     * 释放锁
     *
     * @param lockName   锁的key
     * @param identifier 释放锁的标识
     * @return
     */
    public boolean releaseLock(String lockName, String identifier, int index) {
        Jedis conn = null;
        String lockKey = "lock:" + lockName;
        boolean retFlag = false;
        try {
            conn = jedisPool.getResource();
            conn.auth(password);
            conn.select(index);
            while (true) {
                // 监视lock，准备开始事务
                conn.watch(lockKey);
                // 通过前面返回的value值判断是不是该锁，若是该锁，则删除，释放锁
                if (identifier.equals(conn.get(lockKey))) {
                    Transaction transaction = conn.multi();
                    transaction.del(lockKey);
                    List<Object> results = transaction.exec();
                    if (results == null) {
                        continue;
                    }
                    retFlag = true;
                }
                conn.unwatch();
                break;
            }
        } catch (JedisException e) {
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return retFlag;
    }

    public boolean set(String key, String value, int index) {
        try {
            Jedis jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            jedis.set(key, value);
            jedis.close();
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }

    }

    /**
     * 递增
     *
     * @param key
     * @param index
     */
    public void incr(String key, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            jedis.incr(key);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 对key的值做减减操作,如果key不存在,则设置key为-1
     *
     * @param key
     * @return
     */
    public void decr(String key, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            jedis.decr(key);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 设置key的超时时间为seconds
     *
     * @param key
     * @param seconds
     * @return
     */
    public void expire(String key, int seconds, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            jedis.expire(key, seconds);
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }


    public String get(String key, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            return jedis.get(key);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

//    public static void setHash(String key,String field,Object value){
//        Jedis jedis=null;
//        try {
//            jedis = jedisPool.getResource();
//            byte[] byteKey = SerializeUtil.serialize(key);
//            byte[] byteField=SerializeUtil.serialize(field);
//            byte[] byteValue=SerializeUtil.serialize(value);
//            jedis.hset(byteKey,byteField,byteValue);
//            jedis.close();
//        }catch (Exception ex){
//
//        }finally {
//            if(jedis!=null){
//                jedis.close();
//            }
//        }
//    }

    public boolean setHash(String key, String field, String value, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            jedis.hset(key, field, value);
            return true;
        } catch (Exception ex) {
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }

    }

    public boolean setHashExpire(String key, String field, String value, int seconds, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            jedis.hset(key, field, value);
            jedis.expire(key, seconds);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public String getHashValue(String key, String field, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            return jedis.hget(key, field);
        } catch (Exception ex) {
            return null;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public boolean hexists(String key, String field, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            return jedis.hexists(key, field);
        } catch (Exception ex) {
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public Map<String, String> hgetAll(String key, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            return jedis.hgetAll(key);
        } catch (Exception ex) {
            return null;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public boolean setex(String key, int seconds, String value, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            jedis.setex(key, seconds, value);
            return true;
        } catch (Exception ex) {
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 通过key给指定的value加值,如果key不存在,则这是value为该值
     *
     * @param key
     * @param integer
     * @return
     */
    public Long incrBy(String key, long integer, int index) {

        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
        } catch (Exception ex) {
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return jedis.incrBy(key, integer);
    }

    public Long setnx(String key, int seconds, String value, int index) {
        Long flag = 0L;
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            flag = jedis.setnx(key, value);
            jedis.setex(key, seconds, value);
        } catch (Exception ex) {
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return flag;
    }

//    public static void get

//    public static Object getHashField(String key,Object field){
//        Jedis jedis=null;
//        try{
//            jedis=jedisPool.getResource();
//            byte[] byteKey=SerializeUtil.serialize(key);
//            byte[] byteField=SerializeUtil.serialize(field);
//            return jedis.hget(byteKey,byteField);
//        }catch (Exception ex){
//            return null;
//        }finally {
//            if(jedis!=null){
//                jedis.close();
//            }
//        }
//    }

    public Map<String, String> getHash(String key, int index) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            return jedis.hgetAll(key);
        } catch (Exception ex) {
            return null;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public boolean exists(String key, int index) {
        boolean result = false;
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            result = jedis.exists(key);
        } catch (Exception e) {
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    public Long incr(String key, int seconds, int index) {
        Long flag = 0L;
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            flag = jedis.incr(key);
            jedis.expire(key, seconds);
        } catch (Exception ex) {
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return flag;
    }

    public boolean sismember(String key, String value, int index) {
        boolean flag = false;
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            flag = jedis.sismember(key, value);
        } catch (Exception ex) {
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return flag;
    }

    public Long sadd(String key, String value, int index) {
        Long flag = 0L;
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            flag = jedis.sadd(key, value);
        } catch (Exception ex) {
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return flag;
    }

    public Long delKey(String key, int index) {
        Long flag = 0L;
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.select(index);
            flag = jedis.del(key);
        } catch (Exception ex) {
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return flag;
    }

    public Boolean delValue(String key,String value){
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.lrem(key,0,value);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }
    /**
     * 添加list
     *
     * @param key
     * @return
     */
    public Boolean lpush(String key,String value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.lpush(key,value);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }



    /**
     * 删除list
     *
     * @param key
     * @return
     */
    public Boolean ltrim(String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            jedis.ltrim(key,0,0);
            jedis.lpop(key);
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取指定范围的记录
     * 下标从0开始 -1表示最后一个元素
     * @param key
     * @return
     */
    public List<String> lrange(String key, long start, long end) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            jedis.auth(password);
            List<String> result = jedis.lrange(key,start,end);
            return result;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

}
